/**
 * 
 */
package jvs.core.http;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

/**
 * @author qiangli
 *
 */
public class Request extends Message {
	public final static String METHOD_POST = "POST";
	
	public final static String METHOD_GET = "GET";
	
	public final static String METHOD_HEAD = "HEAD";

	// request line
	public String method;

	public String requestUri;

	public String httpVersion;

	public String requestJid;
	
	public String path;
	
	// base
	public String base;

	public String referer;
	
	public String from; //jid
	
	public String host; //localhost:10080
	
	public String expect;
	
	public String via;
	
	public String range;
	
	public String ifModifiedSince;
	
	public String userAgent;

	public List<NVPair> params;

	//
	public Context context;
	
	public Request() {
	}
	
	public String getParam(String name) {
		for (NVPair nv: params) {
			if (nv.name.equals(name)) {
				return nv.getValue();
			}
		}
		return null;
	}
	
	public void parse(InputStream is) throws IOException {
		startLine = readLine(is);
		
		parseStartLine();

		//
		headers = new ArrayList<String>();
		String line = null;
		for (int i = 0;;) {
			line = readLine(is);
			if (line == null || line.length() == 0) {
				break;
			} else if (line.charAt(0) == '\t' || line.charAt(0) == ' ') {
				headers.add(i - 1, headers.get(i - 1) + line); // multiple-line
				continue;
			}
			headers.add(i++, line);
			//
			if (line.startsWith("Content-Type:")) {
				contentType = line.substring(13).trim();
			} else if (line.startsWith("Content-Length:")) {
				try {
					contentLength = Integer.parseInt(line.substring(15)
							.trim());
				} catch (Exception e) {
				}
			} else if (line.startsWith("Content-Encoding:")) {
				contentEncoding = line.substring(17).trim();
			} else if (line.startsWith("Referer:")) {
				referer = line.substring(8).trim();
			} else if (line.startsWith("Host:")) {
				host = line.substring(5).trim();
			} else if (line.startsWith("From:")) {
				from = line.substring(5).trim();
			} else if (line.startsWith("Base:")) {
				base = line.substring(5).trim();
			} else if (line.startsWith("Via:")) {
				via = line.substring(4).trim();
			} else if (line.startsWith("Range:")) {
				range = line.substring(6).trim();
			} else if (line.startsWith("If-Modified-Since:")) {
				ifModifiedSince = line.substring(18).trim();
			} else if (line.startsWith("User-Agent:")) {
				userAgent = line.substring(11).trim();
			}	
		}

		String charset = "UTF-8";
		// TODO parse charset

		params = new ArrayList<NVPair>();
		Utils.parseUri(params, requestUri, charset);

		// body
		if (contentLength > 0) {
			byte[] content = new byte[contentLength];
			int cnt = 0;
			for (int i = 0; i < contentLength; i += cnt) {
				cnt = is.read(content, i, contentLength - i);
			}
			Utils.parseContent(params, content, charset);
		}
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("method: " + method);
		sb.append(" request uri: " + requestUri);
		sb.append(" http version: " + httpVersion);
		sb.append(" jid: " + requestJid);
		sb.append(" path: " + path);
		return sb.toString();
	}

	private void parseStartLine() {
		log("Request Line: |" + startLine + "|");

		StringTokenizer st = new StringTokenizer(startLine);
		String[] r = new String[st.countTokens()];
		for (int i = 0; st.hasMoreTokens(); i++) {
			r[i] = st.nextToken();
		}

		method = r[0].trim().toUpperCase();
		requestUri = r[1];
		httpVersion = r[2];
		
		//
		requestJid = Utils.parseJid(requestUri);
		path = Utils.parsePath(requestUri);
	}
	
	public boolean isPost() {
		return this.method.equals(METHOD_POST);
	}
	
	public boolean isGet() {
		return this.method.equals(METHOD_GET);
	}
}